package com.ibm.db2oncampus.portal.usuario.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpSession;

import com.ibm.db2oncampus.portal.domain.domain.DomainCountry;
import com.ibm.db2oncampus.portal.domain.domain.DomainExperienceType;
import com.ibm.db2oncampus.portal.domain.domain.DomainGraduationLevel;
import com.ibm.db2oncampus.portal.domain.domain.DomainWhoIAm;
import com.ibm.db2oncampus.portal.domain.exception.DomainException;
import com.ibm.db2oncampus.portal.domain.service.DomainService;
import com.ibm.db2oncampus.portal.framework.beans.FacesBeanSupport;
import com.ibm.db2oncampus.portal.framework.service.InvalidDataException;
import com.ibm.db2oncampus.portal.usuario.domain.Experience;
import com.ibm.db2oncampus.portal.usuario.domain.Person;
import com.ibm.db2oncampus.portal.usuario.domain.Role;
import com.ibm.db2oncampus.portal.usuario.service.PersonService;
import com.ibm.db2oncampus.portal.util.JSFUtil;

/**
 * 
 * @author Wellington
 *
 */
public class PersonBean extends FacesBeanSupport implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private final String LOGGED_USER_SESSION_ATTRIBUTE = "loggedUser";
	
	// Services invoked
	private PersonService personService;
	private DomainService domainService;
	
	// Domains used in the forms
	List<DomainCountry> countriesList = null;
	List<DomainWhoIAm> userTypeList = null;
	List<DomainExperienceType> experienceTypeList = null;
	List<DomainGraduationLevel> graduationLevelList = null;
	
	// Required for registration
	private Person person = new Person();
	private String passwordForConfirmation;

	

	
	public PersonBean() {
		
		Person loggedUser = this.getLoggedUser();
		
		if(loggedUser != null) {
			this.person = loggedUser;
			this.passwordForConfirmation = loggedUser.getPassword();
		}
	}
	
	public String saveNewUser() {
		try {
			personService.save(this.getPerson());
			this.addMessage("User " + this.getPerson().getUserId() + " registered successfully", null);
			
			HttpSession httpSession = (HttpSession) this.getFacesContext().getExternalContext().getSession(false);
			httpSession.setAttribute(LOGGED_USER_SESSION_ATTRIBUTE, this.getPerson());
			
			return "home";
		} catch (InvalidDataException ide) {
			ide.printStackTrace();
			
			for(String error : personService.getErrors()) {
				this.addError(error, null);
			}
			personService.getErrors().clear();
		}
		
		return null;
	}
	
	public void saveExperienceInformationForUser() {
		try {
			
			for(Experience e : this.getPerson().getExperience()) {
				if(e.getExperienceId() <= 0) {
					e.setEnteredExperience(false);
					e.setExperienceId(null);
				}
			}
			
			personService.saveCompleteProfile(this.getPerson());
			
			this.getFacesContext().addMessage("experienceListForm", new FacesMessage("Experience information for " + this.getPerson().getUserId() + " saved successfully"));
		} catch(InvalidDataException ide) {
			ide.printStackTrace();
			
			for(String error : personService.getErrors()) {
				this.getFacesContext().addMessage("experienceListForm", new FacesMessage(error));
			}
			personService.getErrors().clear();
		}
	}
	
	public void savePersonalInformationForUser() {
		try {
			
			personService.saveCompleteProfile(this.getPerson());
			
			this.getFacesContext().addMessage("personalInformationForm", new FacesMessage("Personal information for " + this.getPerson().getUserId() + " saved successfully"));
		} catch(InvalidDataException ide) {
			ide.printStackTrace();
			
			for(String error : personService.getErrors()) {
				this.getFacesContext().addMessage("personalInformationForm", new FacesMessage(error));
			}
			personService.getErrors().clear();
		}
	}
	
	public void saveSecurityInformationForUser() {
		try {
			
			personService.saveCompleteProfile(this.getPerson());
			
			this.getFacesContext().addMessage("securityForm", new FacesMessage("Security information for " + this.getPerson().getUserId() + " saved successfully"));
		} catch(InvalidDataException ide) {
			ide.printStackTrace();
			
			for(String error : personService.getErrors()) {
				this.getFacesContext().addMessage("securityForm", new FacesMessage(error));
			}
			personService.getErrors().clear();
		}
	}
	
	public String cancelUserRegistration() {
		return "home";
	}
	
	public String cancelCompleteProfile() {
		return "home";
	}

	public String removeSubscriptionForUser() {
		
		this.personService.remove(this.getLoggedUser());
		
		return "removeSubscription";
	}
	
	public DataModel getRolesDataModel() {
		DataModel rolesDataModel = new ListDataModel();
		
		List<Role> roles = new ArrayList<Role>(this.getPerson().getRolesPlayed());
		
		rolesDataModel.setWrappedData(roles);
		return rolesDataModel;
	}
	
	public void validateDateOfBirth(FacesContext context, UIComponent toValidate, Object value) {
		Date birthDay = (Date) value;

		
		if(birthDay.after(new Date())) {
			((UIInput)toValidate).setValid(false);
			FacesMessage message = new FacesMessage("Birthday cannot be after today");
			context.addMessage(toValidate.getClientId(context), message);
		}

	}
	
	// Domain Values
	public List<SelectItem> getListOfUserTypes() {
		List<SelectItem> selectItems = new ArrayList<SelectItem>();
		
		try {
			if(this.userTypeList == null || this.userTypeList.isEmpty()) {
				this.userTypeList = domainService.listAllWhoIAm();
			}
			for(DomainWhoIAm d : this.userTypeList) {
				selectItems.add(new SelectItem(d.getId().getValue(), d.getDescription()));
			}
		} catch (DomainException e) {
			JSFUtil.addGlobalMessage(e.getMessage());
		}
		
		return selectItems;
	}
	
	public List<SelectItem> getListOfCountries() {
		List<SelectItem> selectItems = new ArrayList<SelectItem>();
		
		try {
			if(this.countriesList == null || this.countriesList.isEmpty()) {
				this.countriesList = domainService.listAllCountry();
			}
			for(DomainCountry d : this.countriesList) {
				selectItems.add(new SelectItem(d.getId().getValue(), d.getId().getValue()));
			}
		} catch (DomainException e) {
			JSFUtil.addGlobalMessage(e.getMessage());
		}
		
		return selectItems;
	}
	
	public List<SelectItem> getListOfExperienceTypes() {
		List<SelectItem> selectItems = new ArrayList<SelectItem>();
		
		try {
			if(this.experienceTypeList == null || this.experienceTypeList.isEmpty()) {
				this.experienceTypeList = domainService.listAllExperienceTypes();
			}
			for(DomainExperienceType d : this.experienceTypeList) {
				selectItems.add(new SelectItem(d.getId().getValue(), d.getDescription()));
			}
		} catch (DomainException e) {
			JSFUtil.addGlobalMessage(e.getMessage());
		}
		
		return selectItems;
	}
	
	
	public List<SelectItem> getListOfGraduationLevels() {
		List<SelectItem> selectItems = new ArrayList<SelectItem>();
		
		try {
			if(this.graduationLevelList == null || this.graduationLevelList.isEmpty()) {
				this.graduationLevelList = domainService.listAllGraduationLevels();
			}
			for(DomainGraduationLevel d : this.graduationLevelList) {
				selectItems.add(new SelectItem(d.getId().getValue(), d.getDescription()));
			}
		} catch (DomainException e) {
			JSFUtil.addGlobalMessage(e.getMessage());
		}
		
		return selectItems;
	}
	
	// Edit buttons

	
	// Getters and Setters
	
	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public String getPasswordForConfirmation() {
		return passwordForConfirmation;
	}
	
	public void setPasswordForConfirmation(String passwordForConfirmation) {
		this.passwordForConfirmation = passwordForConfirmation;
	}

	public PersonService getPersonService() {
		return personService;
	}

	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}
	
	public void setDomainService(DomainService domainService) {
		this.domainService = domainService;
	}
	
	
	
}